package com.aiwiown.snackmq.broker.handler;

import com.aiwiown.snackmq.broker.auth.AuthorizationService;
import com.aiwiown.snackmq.cluster.metadata.MetadataManager;
import com.aiwiown.snackmq.common.auth.Action;
import com.aiwiown.snackmq.common.handler.MessageHandler;
import com.aiwiown.snackmq.common.handler.RequestContext;
import com.aiwiown.snackmq.common.message.Message;
import com.aiwiown.snackmq.common.message.MessageStatus;
import com.aiwiown.snackmq.common.message.MessageType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 【新增/修复】处理控制台绑定队列到交换机请求的处理器。
 * 此前可能因实现错误（例如响应消息未设置类型）或文件缺失，导致客户端请求超时。
 * 这个实现确保了总会返回一个带有正确类型 (RESPONSE) 的响应。
 */
@Slf4j
@RequiredArgsConstructor
public class BindQueueHandler implements MessageHandler {

    private final MetadataManager metadataManager;
    private final AuthorizationService authorizationService;

    @Override
    public MessageType getMessageType() {
        return MessageType.BIND_QUEUE_REQUEST;
    }

    @Override
    public void handle(RequestContext ctx, Message request) {
        try {
            String exchangeName = request.getProperty("exchangeName");
            // 在SnackMQ中，队列即主题。客户端将队列名放在了消息的topic字段中。
            String queueName = request.getTopic();
            String routingKey = request.getProperty("routingKey");

            // 授权检查：绑定操作修改了主题的路由行为，因此需要对该主题有MANAGE权限。
            authorizationService.authorize(request.getProperty("authToken"), Action.MANAGE, new AuthorizationService.Resource("TOPIC", queueName));

            if (exchangeName == null || queueName == null || routingKey == null) {
                throw new IllegalArgumentException("ExchangeName, Topic/QueueName, and RoutingKey properties are required.");
            }

            metadataManager.bindQueue(queueName, exchangeName, routingKey, status -> {
                Message response;
                if (status.isOk()) {
                    response = Message.builder().type(MessageType.RESPONSE).messageId(request.getMessageId()).status(MessageStatus.SUCCESS).build();
                } else {
                    log.error("Failed to bind queue via Raft: {}", status.getErrorMsg());
                    response = Message.builder().type(MessageType.RESPONSE).messageId(request.getMessageId()).status(MessageStatus.FAILED).errorMessage(status.getErrorMsg()).build();
                }
                ctx.writeResponse(response);
            });
        } catch (Exception e) {
            log.error("Error processing bind queue request", e);
            Message response = Message.builder().type(MessageType.RESPONSE).messageId(request.getMessageId()).status(MessageStatus.FAILED).errorMessage("Internal server error: " + e.getMessage()).build();
            ctx.writeResponse(response);
        }
    }
}